# -*- coding: utf-8 -*-

from __future__ import with_statement
from StringIO import StringIO # cStringIO has issues with Unicode.
import os
import shutil
from uuid import uuid4 as get_uuid

from ws9 import stream


class FileOperation(object):
    
    def __init__(self, tab_width=4):
        self.tab_width = int(tab_width)
        self.operations = []
        self.__endings = None
        self.__indent_type = None
    
    def __get_endings(self):
        return self.__endings
    
    def __set_endings(self, value):
        if value not in ['\r\n', '\r', '\n']:
            return
        self.__endings = value
    
    def __del_endings(self):
        self.__endings = None
    
    def __get_indent_type(self):
        return self.__indent_type
    
    def __set_indent_type(self, value):
        if value not in '\t ':
            return
        self.__indent_type = value
    
    def __del_indent_type(self):
        self.__indent_type = None
    
    @staticmethod
    def get_filestreams(filename, fileout=None, in_memory=False):
        if fileout:
            fp_in, fp_out = open(filename), open(fileout, 'w')
        elif (not fileout) and in_memory:
            temp_fp, fp_in = open(filename), StringIO()
            copy_stream(temp_fp, fp_in)
            temp_fp.close()
            fp_in.seek(0)
            fp_out = open(filename, 'w')
        elif not (fileout or in_memory):
            directory, fileout = os.path.split(filename)
            new_filename = os.path.join(directory, get_uuid())
            while os.path.isfile(new_filename):
                new_filename = os.path.join(directory, get_uuid())
            shutil.move(filename, new_filename)
            fp_in, fp_out = open(new_filename), open(filename, 'w')
        return fp_in, fp_out
    
    def execute(self, fp_in, fp_out, close=True):
        doc = stream.StreamDocument(fp_in, tab_width=self.tab_width)
        if self.endings:
            doc.endings = self.endings
        if self.indent_type:
            doc.indent_type = self.indent_type
        fp_out.writelines(str(line) for line in doc)
        if close:
            fp_in.close(), fp_out.close()


def is_filelike(obj, mode='r'):
    if hasattr(obj, 'mode'):
        mode = obj.mode
    result = hasattr(obj, 'close')
    if 'r' in mode:
        result = result & all(hasattr(obj, attr) for attr in
            ['read', 'readline', 'readlines'])
    if 'w' in mode:
        result = result & all(hasattr(obj, attr) for attr in
            ['write', 'writelines'])
    return result


def copy_stream(stream_in, stream_out, chunk_size=65536):
    if not is_filelike(stream_in, mode='r'):
        raise IOError('Invalid input stream: %r' % (stream_in,))
    if not is_filelike(stream_out, mode='w'):
        raise IOError('Invalid output stream: %r' % (stream_in,))
    if chunk_size > 0:
        curr_data = stream_in.read(chunk_size)
        while curr_data:
            stream_out.write(curr_data)
            curr_data = stream_in.read(chunk_size)
    else:
        stream_out.write(stream_in.read())
